/*
 * PublicTool.cpp
 *
 *  Created on: 2016-10-20
 *      Author: root
 */
#include"PublicTool.h"
#include<math.h>
#include<sys/timeb.h>
#include"PublicLog.h"
//__asm__(".symver __isoc99_sscanf,sscanf@GLIBC_2.2.5");
//localtime_r多线程慎用
#if 1
//2015-03-18 14:26:20.000
void GetDateTimeString(char*str,size_t len){
    char timestr[32]={0};
    struct timeb rawtime={0};
    ftime(&rawtime);
    struct tm timeinfo={0};
    localtime_r(&rawtime.time,&timeinfo);  
//  strftime(timestr,len,"%F %T",&timeinfo);
//MINGW32不支持%F %T    	
    strftime(timestr,len,"%Y-%m-%d %H:%M:%S",&timeinfo);
    snprintf(str,len,"%s.%03hu",timestr,rawtime.millitm);
}
#else
//2015-03-18 14:26:20
void GetDateTimeString(char*str,size_t len){
    time_t rawtime=0;
    struct tm timeinfo={0};
    time(&rawtime);
    localtime_r(&rawtime,&timeinfo);
    strftime(str,len,"%F %T",&timeinfo);
}
#endif
//2015-03-18
void GetDateString(char*str,size_t len,time_t seektime,int flag){
    time_t rawtime=0;
    struct tm timeinfo={0};
    time(&rawtime);
	rawtime=rawtime+seektime;
    localtime_r(&rawtime,&timeinfo);
//  strftime(str,len,"%F",&timeinfo);
	if(flag==1){
		strftime(str,len,"%Y%m%d",&timeinfo);
	}else{
		strftime(str,len,"%Y-%m-%d",&timeinfo);
	}
}
//获取今天日期
int  GetToDay(){
    time_t rawtime=0;
    struct tm timeinfo={0};
    time(&rawtime);
    localtime_r(&rawtime,&timeinfo);
    return timeinfo.tm_mday;
}
#if __MINGW32__
ssize_t getline(char**buff,size_t*bufflen,FILE*fp){
    ssize_t readsize=0;
    if(*buff==NULL){
       *buff=(char*)malloc(1024);
    }
    *bufflen=1024;
    if(fgets(*buff,*bufflen,fp)!=NULL){
       return strlen(*buff);  
    }else{
       return -1; 
    }
    return -1;
}
static inline unsigned long mktime (unsigned int year, unsigned int mon,
    unsigned int day, unsigned int hour,
    unsigned int min, unsigned int sec)
        {
    if (0 >= (int) (mon -= 2)) {    /* 1..12 -> 11,12,1..10 */
         mon += 12;      /* Puts Feb last since it has leap day */
         year -= 1;
    }

    return (((
             (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +
             year*365 - 719499
          )*24 + hour /* now have hours */
       )*60 + min /* now have minutes */
    )*60 + sec; /* finally seconds */
}

int strptime(const char*datetime,const char*formant,struct tm*tm_time){
    if(strlen(datetime)==8){      
       sscanf(datetime,"%04d%02d%02d",&tm_time->tm_year,&tm_time->tm_mon,&tm_time->tm_mday);
    }else
    if(strlen(datetime)==14){
       sscanf(datetime,"%04d%02d%02d%02d%02d%02d",&tm_time->tm_year,&tm_time->tm_mon,&tm_time->tm_mday,
       &tm_time->tm_hour,&tm_time->tm_min,&tm_time->tm_sec);
    }
    time_t timestamp=(time_t)mktime(tm_time->tm_year,tm_time->tm_mon,tm_time->tm_mday,
    tm_time->tm_hour,tm_time->tm_min,tm_time->tm_sec);
    localtime_r(&timestamp,tm_time);
    return 0;
}
#endif
time_t strtotime(const char*datetime,int bEnd){
	if(strlen(datetime)==8||strlen(datetime)==14){
		struct tm tm_time={0};
		time_t unixtime;
		strptime(datetime,"%Y%m%d%H%M%S", &tm_time);      
		unixtime = mktime(&tm_time);
//时间偏移
        if(bEnd==1&&strlen(datetime)==8){
           unixtime+=86400;
        }
        return unixtime;
    }else
    if(strlen(datetime)==10){
        time_t unixtime=atol(datetime);
        return unixtime;
    }
    return -1;
}

char*timetostr(time_t timestamp,char*strtime,size_t maxsize,const char*formnt){
    if(strtime){
		struct tm   tmptm={0};
		localtime_r(&timestamp,&tmptm);
		memset(strtime,0,maxsize);
		strftime(strtime,maxsize,formnt,&tmptm);
	}
    return strtime;
}

std::string GetBandWidthDescr(uint64_t BandWithd){
    std::string Descr;
    char Buffer[32]={0};
    if(BandWithd<1e+003){
		sprintf(Buffer,PRU64" bps",BandWithd);
    }else
    if(BandWithd<1e+006){
		double val=1.0*BandWithd/(1e+003);
		sprintf(Buffer,"%0.2f kbps",val);
    }else
    if(BandWithd<1e+009){
		double val=1.0*BandWithd/(1e+006);
		sprintf(Buffer,"%0.2f mbps",val);
    }else
    if(BandWithd<1e+012){
		double val=1.0*BandWithd/(1e+009);
		sprintf(Buffer,"%0.2f gbps",val);
    }else{
		double val=1.0*BandWithd/(1e+012);
		sprintf(Buffer,"%0.2f tbps",val);
    }
    Descr=Buffer;
    return Descr;
}
int CheckIsAllNumber(const char*str,int len){
    int i;
    for(i=0;i<len;i++){
        if(str[i]<'0'||str[i]>'9'){
            return 0;
        }
    }
    if(i==0)return 0;
    return 1;
}

const char*strichr(const char*string,char c){
    const char*p=strchr(string,c);
    if(p==NULL&&((c>='A'&&c<='Z')||(c>='a'&&c<='z'))){
        if(c>='A'&&c<='Z'){
            p=strchr(string,c+32);
        }else{
            p=strchr(string,c-32);
        }
    }
    return p;
}
const char*strnchr(const char*s,size_t count,char c){
    const char*end=s+count;
    while(s<end){
        if(*s == c){
            return s;
        }
        s++;
    }
    return NULL;
}
int CreateFolder(const char*path,int recursive){
#ifndef __MINGW32__	
    char command[1024]={0};
    sprintf(command,"mkdir %s %s -m775",recursive?"-p":"",path);
    if(system(command)!=0){
		WRONG("Unable to create folder %s", path);
		return -1;
    }
#endif	
    return 0;
}

#if 1
int64_t GetMenSize(){
    return 0;
}
#else
#include<proc/readproc.h>
int64_t GetMenSize(){
    int64_t memsize=0;
    proc_t*p=get_proc_stats(getpid(),NULL);
    if(p){
       freeproc(p);
    }else{
       WRONG("内存获取失败");
    }
    return memsize;
}
#endif
void*Malloc(size_t __size,int __c){
    void*ptr=malloc(__size);
    if(ptr)memset(ptr,__c,__size);
    return ptr;
}
void*Free(void*__ptr){
    if(__ptr)free(__ptr);
    return NULL;
}
static timeval starttime[16]={0};
void ReSetStartTime(int flag){
	flag=flag%16;
    starttime[flag].tv_sec=0;
    starttime[flag].tv_usec=0;
    gettimeofday(&starttime[flag],NULL);
}
int  GetEndTime(int flag){
	flag=flag%16;
    struct timeval endtime={0,0};
    gettimeofday(&endtime,NULL);
    return GetTimerSubCommon(endtime,starttime[flag]);
}
int  GetEndTimeEx(int flag){
	flag=flag%16;
	struct timeval endtime={0,0};
    gettimeofday(&endtime,NULL);
    return GetTimerSubCommonEx(endtime,starttime[flag]);
}
int GetTimerSubCommon(timeval timeend,timeval timestart){
    int usetime=0;
    timeval timeresult={0};
    timersub(&timeend,&timestart,&timeresult);
    if(timeresult.tv_sec==0&&timeresult.tv_usec<1000){
		usetime=1;
    }else{
		usetime=timeresult.tv_sec*1000+timeresult.tv_usec/1000;
    }
    return usetime;
}
int GetTimerSubCommonEx(timeval timeend,timeval timestart){
    int usetime=0;
    timeval timeresult={0};
    timersub(&timeend,&timestart,&timeresult);
    usetime=timeresult.tv_sec*1000000+timeresult.tv_usec;
    return usetime;
}
bool CheckDuringAlarmTime(int StartHour,int EndHour,const char*Descr){
    time_t timep=time(NULL);
    struct tm m_tnow={0};
    localtime_r(&timep,&m_tnow);
    if(m_tnow.tm_hour>StartHour&&m_tnow.tm_hour<EndHour){
		INFOEX("当前时间%04d-%02d-%02d %02d:%02d:%02d 进行 %s 检测(Start:%d,end:%d)",
		m_tnow.tm_year+1900,m_tnow.tm_mon + 1,m_tnow.tm_mday,
		m_tnow.tm_hour,m_tnow.tm_min,m_tnow.tm_sec,Descr,StartHour,EndHour);
		return true;
    }else{
		INFOEX("当前时间%04d-%02d-%02d %02d:%02d:%02d 不进行 %s 检测(Start:%d,end:%d)",
		m_tnow.tm_year+1900,m_tnow.tm_mon + 1,m_tnow.tm_mday,
		m_tnow.tm_hour,m_tnow.tm_min,m_tnow.tm_sec,Descr,StartHour,EndHour);
		return false;
    }
    return false;
}
#if 1
#ifdef __MINGW32__
#include<synchapi.h>
#endif
void sleep_s(int nssleeptime){
    sleep(nssleeptime);
}
void usleep_s(int nssleeptime){
#ifdef __MINGW32__    
    Sleep(nssleeptime);
#else
    usleep(nssleeptime*1000);
#endif    
}
#else
void sleep_s(int nssleeptime){
    struct timeval wait = {0,0};
    wait.tv_sec=nssleeptime;
    select(0, NULL, NULL, NULL, &wait);
}
void usleep_s(int nssleeptime){
    struct timeval wait = {0,0};
    wait.tv_sec=nssleeptime/1000000;
    wait.tv_usec=nssleeptime%1000000;
    select(0, NULL, NULL, NULL, &wait);
}
#endif
#include<sys/stat.h>
#ifdef __MINGW32__
void InitFork(){}
#else
#include<sys/wait.h>
void InitFork(){
    if(fork()!=0) exit(0);
    setsid();
    int fd = open ("/dev/null", O_RDWR, 0);
    if (fd != -1){
		dup2 (fd, STDIN_FILENO);
		dup2 (fd, STDOUT_FILENO);
		dup2 (fd, STDERR_FILENO);
		if(fd > 2)
			close (fd);
    }
    umask(0027);
}
#endif
static char FullPath[1024]={0};//全路径
static char WorkPath[1024]={0};//工作路径
static char AppName[1024]={0};//APP名字
static char ConfigFileName[1024]={0};//配置文件
#ifdef __MINGW32__
#include<libloaderapi.h>
#endif
void InitWorkPath(){
    char buff[1024]={0};
    char*Pos=NULL;
#ifdef __MINGW32__	
    GetModuleFileName(NULL,buff,1024);
	strcpy(FullPath,buff);
	strcpy(WorkPath,FullPath);
    Pos=strrchr(WorkPath,'\\');
	setbuf(stdout,0);
#else
	snprintf(buff,sizeof(buff),"/proc/%d/exe",getpid());
    readlink(buff,FullPath,1024);
	strcpy(WorkPath,FullPath);
    Pos=strrchr(WorkPath,'/');
#endif	
    if(Pos!=NULL)Pos[0]='\0';
    strcpy(AppName,Pos+1);
	char*Pos2=strrchr(Pos+1,'.');
	if(Pos2!=NULL&&strcasecmp(Pos2+1,"exe")==0){
		Pos2[0]='\0';
		snprintf(ConfigFileName,sizeof(ConfigFileName),"%s.conf",Pos+1);
	}else{
		snprintf(ConfigFileName,sizeof(ConfigFileName),"%s.conf",AppName);
	}
    chdir(WorkPath);
#if 1
	WARN("工作路径:%s",WorkPath);
#else	
#ifdef USE_CMD_COLOR
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x0E);
	printf("工作路径:%s\n",WorkPath);
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x0F);
#else	
    printf("\033[01;33m工作路径:%s\033[0m\n",WorkPath);
#endif
#endif
}
const char*GetConfigFileName(){
    if(strlen(ConfigFileName)==0){
		InitWorkPath();
    }
    return ConfigFileName;
}
const char*GetAppName(){
    if(strlen(AppName)==0){
		InitWorkPath();
    }
    return AppName;
}
const char*GetWorkPath(){
    if(strlen(WorkPath)==0){
		InitWorkPath();
    }
    return WorkPath;
}

void UpdateFileType(struct dirent*dirp,const char*Path){
#ifndef __MINGW32__    
    if(dirp->d_type==0){
		struct stat sb;
		char localfilename[1024]={0};
		if(Path!=NULL){
			sprintf(localfilename,"%s/%s",Path,dirp->d_name);
		}else{
			strcpy(localfilename,dirp->d_name);
        }
		if(stat(localfilename,&sb)!=-1){
			if(S_ISDIR(sb.st_mode)){
				dirp->d_type=4;
			}else
			if(S_ISREG(sb.st_mode)){
				dirp->d_type=8;
            }
        }
    }
#endif    
}

int is_file_exist(const char*file_path){
	struct stat64 sb;
    if(stat64(file_path,&sb)!=-1){
		return S_ISREG(sb.st_mode);
    }else{
		return -1;
    }
	return -1;
}
int is_dir_exist(const char*dir_path){
	struct stat64 sb;
    if(stat64(dir_path,&sb)!=-1){
		return S_ISDIR(sb.st_mode);
    }else{
		return -1;
    }
	return -1;
}


int64_t GetFileSize(const char*file){
    struct stat64 sb;
    if(stat64(file,&sb)!=-1){
		return sb.st_size;
    }else{
		return -1;
    }
    return INT64_C(0);
}
std::string GetFileSizeDescr(int64_t filesize){
    std::string Descr;
    char Buffer[32]={0};
#if 1
    static int64_t checksize[]={
           INT64_C(1000),INT64_C(1000000),INT64_C(1000000000),
           INT64_C(1000000000000)};
#else
    static int64_t checksize[]={
           INT64_C(1024),INT64_C(1048576),INT64_C(1073741824),
           INT64_C(1099511627776)};
#endif
//MB,GB以1000为单位
//Mb,Gb以1024为单位
    if(filesize<checksize[0]){
		sprintf(Buffer,PRI64" Byte",filesize);
    }else
    if(filesize<checksize[1]){
		double val=1.0*filesize/checksize[0];
		sprintf(Buffer,"%0.2f KB",val);
    }else
    if(filesize<checksize[2]){
		double val=1.0*filesize/checksize[1];
		sprintf(Buffer,"%0.2f MB",val);
    }else
    if(filesize<checksize[3]){
		double val=1.0*filesize/checksize[2];
		sprintf(Buffer,"%0.2f GB",val);
    }else{
		double val=1.0*filesize/checksize[3];
		sprintf(Buffer,"%0.2f TB",val);
    }
    Descr=Buffer;
    return Descr;
}
#ifdef __MINGW32__
int CheckChildFork(int pid,const char*argvex,...){
	return 0;
}
#else
#include<stdarg.h>
int ExecCreate(char*const argv[]){
    int pid=fork();
    if(pid==0){
       execv(FullPath,argv);
       exit(0);
    }
    return pid;
}
int CheckChildFork(int pid,const char*argvex,...){
    if(pid==0){
		char*argv[20]={NULL};
		argv[0]=AppName;
		va_list argp;
		va_start(argp,argvex); 
		argv[1]=(char*)argvex;
		int argno=2;
		while(1){ 
			const char*para = va_arg(argp,const char*); 
			if(para==NULL) 
			break; 
        	//printf("Parameter #%d is: %s\n", argno, para); 
			argv[argno]=(char*)para;
			argno++; 
		} 
		va_end(argp);
		pid=ExecCreate(argv);
    }else
    if(waitpid(pid,NULL,WNOHANG)!=0){
		pid=0;
    }
    return pid;
}
int CheckChildForkV(int pid,char*argv[]){
	if(pid==0){
		argv[0]=AppName;
		pid=ExecCreate(argv);
	}else
    if(waitpid(pid,NULL,WNOHANG)!=0){
		pid=0;
    }
    return pid;
}
#endif
void GetKeyAndValue(char*key,char*value,char*str){
    sscanf(str,"%[^=]=%s",key,value);
}
char*strreplace(char*str,size_t len,char srcch,char dtsch){
	size_t pos=0;
	while(pos<len){
		if(str[pos]==srcch){
			str[pos]=dtsch;
		}
		pos++;
	}
	return str;
}
void TRIMC(char*str,size_t*len){
    size_t i=0;
    size_t pos=0;
    for(i=0;i<*len;i++){
        if(str[i]=='\0')
            break;
        if( str[i]!=' ' && str[i]!='\t'&&
            str[i]!='\n' && str[i]!='\r'){
            str[pos++]=str[i];
        }
    }
    str[pos]='\0';
    *len=pos;
}
std::string TRIMCPLUS(std::string str){
    size_t begin=str.find(" ",0);
    while(begin!=std::string::npos){
        str.replace(begin,1,"");
        begin=str.find(" ",begin);
    }
    return str;
}
std::string& replace_all(std::string&str,const std::string&old_value,const std::string&new_value){
    while(true){
        std::string::size_type   pos(0);
        if((pos=str.find(old_value))!=std::string::npos)
            str.replace(pos,old_value.length(),new_value);
        else   break;
    }
	return   str;
}
std::string& replace_all_distinct(std::string&str,const std::string&old_value,const std::string&new_value){
	for(std::string::size_type pos(0);pos!=std::string::npos;pos+=new_value.length()){
		if((pos=str.find(old_value,pos))!=std::string::npos)
			str.replace(pos,old_value.length(),new_value);
		else   break;
    }
	return   str;
}
#ifndef __MINGW32__	
#include <spawn.h>
#include <sys/wait.h>
#endif
int RunMySh(const char*filename){
    char command[1024]={0};
	struct timeval starttime={0,0};
	struct timeval endtime={0,0};
	gettimeofday(&starttime,NULL);
    INFOEX("执行一次脚本:%s",filename);
    snprintf(command,1024,"%s/%s",GetWorkPath(),filename);
    if(access(command, F_OK)!= 0){
		INFOEX("脚本:%s 不存在",filename);
    }else{
#ifdef __MINGW32__		
        int ret=system(command);
		gettimeofday(&endtime,NULL);
        INFOEX("脚本:%s 执行结果:%d 耗时:%ld ms",filename,ret,GetTimerSubCommon(endtime,starttime));
#else
		pid_t child_pid=0;  
		int ret=0;  
		int wait_val=0;  
        ret=posix_spawn(&child_pid,command,NULL,NULL,NULL,NULL);
		gettimeofday(&endtime,NULL);
		wait(&wait_val);  
        INFOEX("脚本:%s 执行结果:%d 返回值:%d 耗时:%d ms",filename,ret,wait_val,GetTimerSubCommon(endtime,starttime));
#endif		
    }
    return 0;
}
#ifndef __MINGW32__	
#include"PublicPopen.h"
#include<sys/epoll.h>
int RunMyShPipe(const char*common,int timeout,std::string&buffer){
	int epoll_sock=epoll_create(2);
	FILE*fp=NULL;
	pid_t pid=0;
	int  fd=0;
	buffer="";
	if(epoll_sock==-1){
		WRONG("Create epoll_sock Error");
		return -1;
    }
    struct epoll_event*events=(struct epoll_event*)malloc(sizeof(struct epoll_event)*2);
    if(events==NULL){
		close(epoll_sock);
		WRONG("Create Events Error");
		return -1;
    }
	fp=PublicPopen(common,"r",&pid);
	if(fp==NULL){
		free(events);
		close(epoll_sock);
		WRONG("common:[%s] timeout:%d pid:%d failed",common,timeout,pid);
		return -1;
	}
	INFO("common:[%s] timeout:%d pid:%d",common,timeout,pid);
	fd=fileno(fp);
	do{
		if(fcntl(fd,F_SETFL,fcntl(fd,F_GETFL)|O_NONBLOCK)!=0){
			WRONG("setsockopt O_NONBLOCK err");
		}
		struct epoll_event event={0};
		event.events=EPOLLIN;
		epoll_ctl(epoll_sock,EPOLL_CTL_ADD,fd,&event);
	}while(0);
	time_t starttime=time(NULL);
	while((time(NULL)-starttime)<timeout){
		ReSetStartTime();
		int n=epoll_wait(epoll_sock,events,2,1000);
		int i=0;
		for(i=0;i<n;i++){
			char buff[1024]={0};
			ReSetStartTime();
			int ret=fread(buff,1,512,fp);
			if(ret>0){
				buffer.append(buff);
			}else{
				epoll_ctl(epoll_sock,EPOLL_CTL_DEL,fd,NULL);;
				PublicPclose(fp,pid);
				fp=NULL;
				pid=0;
			}
		}
		if(fp==NULL){
			break;
		}
	}
	if(fp!=NULL){
		buffer.append("\n超时强制结束");
		epoll_ctl(epoll_sock,EPOLL_CTL_DEL,fd,NULL);;
		PublicPcloseShutdown(fp,pid);
	}
	free(events);
	close(epoll_sock);
	return 0;
}
#endif
#include <zlib.h>
uint32_t MakeCRC32(const char*buff,int len){
	return crc32(0,( const Bytef *)buff,len);
}
